package org.equivalence.server.sockets;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;

import org.equivalence.common.FileTransferHeader;

/**
 * This class allows the transfer of an arbitrary number of files from 
 * a disk to stream. 
 * @author gcc
 *
 */
class FileSender {

	private ArrayList<File> files;
	private ArrayList<File> removeFiles;
	private static final int BUFF_SIZE = 16384;
	private byte[] buffer = new byte[BUFF_SIZE];

	
	public FileSender() {
		files  = new ArrayList<File>();
		removeFiles  = new ArrayList<File>();
	}

	//add a file to the list of files to be transferred
	public void addFile(String filename) {
		File newFile = new File(filename);
		files.add(newFile);
	}
	
	//add a file to the list of files to be removed
	public void deleteFile(String filename) {
		File newFile = new File(filename);
		removeFiles.add(newFile);
	}
	

	//writes the files in the list to an outputstream
	public void sendFiles(OutputStream os) throws Exception{	   
		BufferedOutputStream bos  = new BufferedOutputStream(os);
		ObjectOutputStream objOut = new ObjectOutputStream(os);
		
		//how many files to remove
		objOut.writeInt(removeFiles.size());
		//record how many files are in the stream
		objOut.writeInt(files.size());
		objOut.flush();
		
		//names of the files to remove
		for (File remFile: removeFiles) {
			objOut.writeObject(remFile.getPath());
		}
		objOut.flush();
		
		//write the information regarding file names and sizes to the stream
		for (File file: files) {
			//record the size and name of each file in the stream
			FileTransferHeader header;
			if (file.isDirectory()) {
				header = new FileTransferHeader(file.getPath(),-1);
			}
			else {
				header = new FileTransferHeader(file.getPath(),file.length());
			}
			objOut.writeObject(header);
		}
		objOut.flush();

		//write the file data for each file to the stream
		for (File file: files) {
			//don't write folders to the stream as they have no content
			if (file.length()!=0L) {
				FileInputStream fis = new FileInputStream(file);
				
				// put the file data into the stream
				int read = 0;
				while ((read = fis.read(buffer)) > 0) {
					bos.write(buffer, 0, read); 
				}
				bos.flush();
				fis.close();
			}

		}
		objOut.close();
		bos.close();
	}
}
